import { Context, Next } from 'koa';
import logger from '@/utils/logger';
import { ValidationError } from '@/utils/validator';

/**
 * 全局错误处理中间件
 */
export default async function errorHandler(ctx: Context, next: Next) {
  try {
    await next();
  } catch (error: any) {
    // 记录错误日志
    logger.error('请求错误:', {
      method: ctx.method,
      url: ctx.url,
      error: error.message,
      stack: error.stack,
    });

    // 处理验证错误
    if (error instanceof ValidationError) {
      ctx.status = 400;
      ctx.body = {
        success: false,
        message: error.message,
        code: 400,
        errors: error.errors,
      };
      return;
    }

    // 处理数据库错误
    if (error.name === 'SequelizeValidationError') {
      ctx.status = 400;
      ctx.body = {
        success: false,
        message: '数据验证失败',
        code: 400,
        errors: error.errors.map((e: any) => ({
          field: e.path,
          message: e.message,
        })),
      };
      return;
    }

    if (error.name === 'SequelizeUniqueConstraintError') {
      ctx.status = 400;
      ctx.body = {
        success: false,
        message: '数据已存在',
        code: 400,
      };
      return;
    }

    // 处理认证错误
    if (error.message.includes('令牌') || error.message.includes('未授权')) {
      ctx.status = 401;
      ctx.body = {
        success: false,
        message: error.message,
        code: 401,
      };
      return;
    }

    // 处理权限错误
    if (error.message.includes('权限') || error.message.includes('禁止')) {
      ctx.status = 403;
      ctx.body = {
        success: false,
        message: error.message,
        code: 403,
      };
      return;
    }

    // 处理 404 错误
    if (error.message.includes('未找到') || error.status === 404) {
      ctx.status = 404;
      ctx.body = {
        success: false,
        message: error.message || '资源未找到',
        code: 404,
      };
      return;
    }

    // 默认服务器错误
    ctx.status = error.status || 500;
    ctx.body = {
      success: false,
      message: ctx.app.env === 'production' ? '服务器内部错误' : error.message,
      code: ctx.status,
      ...(ctx.app.env !== 'production' && { stack: error.stack }),
    };
  }
}

